﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using TZReport_Util.Log;

namespace TZReport_Util.Util
{
    public sealed class WebUtils
    {
        private int _timeout = 100000;

        private string m_Username;
        private string m_Password;

        private LogHelper logHelper = new LogHelper(typeof(WebUtils));

        public WebUtils()
        {

        }

        public WebUtils(string username, string password)
        {
            m_Username = username;
            m_Password = password;
        }

        /// <summary>
        /// 请求与响应的超时时间
        /// </summary>
        public int Timeout
        {
            get { return this._timeout; }
            set { this._timeout = value; }
        }


        public byte[] GetBytesByPDF(string srcPdfFile,out string failMsg)
        {
            failMsg = string.Empty;
            byte[] arraryByte;
            HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(srcPdfFile);
            req.Method = "GET";

            WebResponse wr = null;
            try
            {
                wr = req.GetResponse();
            }
            catch (WebException wx)
            {
                wr = (HttpWebResponse)wx.Response;
                failMsg = wx.Message;
                return new byte[0];
            }

            StreamReader responseStream = new StreamReader(wr.GetResponseStream(), Encoding.UTF8);
            int length = (int)wr.ContentLength;
            byte[] bs = new byte[length];

            HttpWebResponse response = wr as HttpWebResponse;
            Stream stream = response.GetResponseStream();

            //读取到内存
            MemoryStream stmMemory = new MemoryStream();
            byte[] buffer1 = new byte[length];
            int i;
            //将字节逐个放入到Byte 中
            while ((i = stream.Read(buffer1, 0, buffer1.Length)) > 0)
            {
                stmMemory.Write(buffer1, 0, i);
            }
            arraryByte = stmMemory.ToArray();
            stmMemory.Close();

            return arraryByte;
        }

        public string RemotePost(string url, IDictionary<string, string> headers, object parameters, string contenttype = "application/json", string charset = "utf-8")
        {
            HttpWebRequest req = GetWebRequest(url, "POST");

            req.ContentType = contenttype + ";charset=" + charset;
            //  req.Accept = contenttype + ";charset=" + charset;

            if (headers != null && headers.Count > 0)
            {
                // 加入请求头
                foreach (KeyValuePair<string, string> item in headers)
                {
                    req.Headers.Add(item.Key, item.Value);
                }
            }

            string dataStr = string.Empty;
            if (parameters is string)
            {
                dataStr = parameters.ToString();
            }
            else if (parameters is IDictionary<string, object>)
            {
                IDictionary<string, object> dic = parameters as IDictionary<string, object>;
                if (contenttype.Contains("application/json"))
                {
                    dataStr = JsonXmlUtils.SerializeObject(dic);
                }
                else
                {
                    dataStr = ToolHelper.BuildQuery(parameters as IDictionary<string, object>, charset);
                }
            }

            // 入参日志
            logHelper.Info($"{url}:{dataStr}");

            byte[] postData = Encoding.GetEncoding(charset).GetBytes(dataStr);
            Stream reqStream = req.GetRequestStream();
            reqStream.Write(postData, 0, postData.Length);
            reqStream.Close();

            HttpWebResponse rsp = (HttpWebResponse)req.GetResponse();
      
            Encoding encoding = Encoding.GetEncoding(string.IsNullOrWhiteSpace(rsp.CharacterSet) ? charset : rsp.CharacterSet);
            return GetResponseAsString(rsp, encoding);
        }

        public string DoGet(string url, string charset, List<KeyValuePair<string, object>> headers = null)
        {
            HttpWebRequest req = GetWebRequest(url, "GET");
            req.ContentType = "application/x-www-form-urlencoded;charset=" + charset;

            if (headers != null && headers.Count > 0)
            {
                foreach (var item in headers)
                {
                    string val = string.Empty;
                    if (item.Value != null)
                        val = item.Value.ToString();
                    req.Headers.Add(item.Key, val);
                }
            }

            HttpWebResponse rsp;
            try
            {
                rsp = (HttpWebResponse)req.GetResponse();
            }
            catch (WebException wx)
            {
                rsp = (HttpWebResponse)wx.Response;
            }

            string rspChat = string.Empty;
            if (rsp != null)
            {
                if (string.IsNullOrWhiteSpace(rsp.CharacterSet))
                    rspChat = charset;
                else
                    rspChat = rsp.CharacterSet;
            }else
            {
                rspChat = "utf-8";
            }

            Encoding encoding = Encoding.GetEncoding(rspChat);
            return GetResponseAsString(rsp, encoding);
        }

        private HttpWebRequest GetWebRequest(string url, string method)
        {
            HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
            req.ServicePoint.Expect100Continue = false;
            req.Method = method;
            req.KeepAlive = true;
            req.UserAgent = "Aop4Net";
            req.Timeout = this._timeout;
            return req;
        }

        /// <summary>
        /// 把响应流转换为文本。
        /// </summary>
        /// <param name="rsp">响应流对象</param>
        /// <param name="encoding">编码方式</param>
        /// <returns>响应文本</returns>
        private string GetResponseAsString(HttpWebResponse rsp, Encoding encoding)
        {
            if (rsp == null)
                return "无数据";

            StringBuilder result = new StringBuilder();
            Stream stream = null;
            StreamReader reader = null;

            try
            {
                // 以字符流的方式读取HTTP响应
                stream = rsp.GetResponseStream();
                reader = new StreamReader(stream, encoding);

                // 按字符读取并写入字符串缓冲
                int ch = -1;
                while ((ch = reader.Read()) > -1)
                {
                    // 过滤结束符
                    char c = (char)ch;
                    if (c != '\0')
                    {
                        result.Append(c);
                    }
                }
            }
            finally
            {
                // 释放资源
                if (reader != null) reader.Close();
                if (stream != null) stream.Close();
                if (rsp != null) rsp.Close();
            }

            return result.ToString();
        }

    }
}
